#include "LibraryLoader.h"
using namespace std;

bool IsLetter(wchar_t c)
{
	if ((c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z'))
		return true;
	return false;
}

bool IsVowel(wchar_t c)
{
    if (!IsLetter(c))
		return false;
	switch (c)
	{
	case L'a':
	case L'e':
	case L'i':
	case L'o':
	case L'u':
	case L'y':
		return true;
	default:
		return false;
	}
}

std::wstring MakeSyllable(std::wstring romaji, WordType type)
{
	if (romaji.empty() || romaji.size() > 4)
		return L"";
	std::wstring s;
	switch (type)
	{
	case WT_HIRAGANA:
		if (romaji == L"a")
			return L"あ";
		else if (romaji == L"e")
			return L"え";
		else if (romaji == L"i")
			return L"い";
		else if (romaji == L"o")
			return L"お";
		else if (romaji == L"u")
			return L"う";
		////////////////////////////
		else if (romaji.size() >= 2 && (romaji[0] == L'k' || romaji[0] == L'c') && romaji[1] != L'h')
		{
			if (romaji == L"ka" || romaji == L"ca")
				return L"か";
			else if (romaji == L"ki")
				return L"き";
			else if (romaji == L"ku" || romaji == L"cu")
				return L"く";
			else if (romaji == L"ke")
				return L"け";
			else if (romaji == L"ko" || romaji == L"co")
				return L"こ";
			else if (romaji == L"kya")
				return L"きゃ";
			else if (romaji == L"kyo")
				return L"きょ";
			else if (romaji == L"kyu")
				return L"きゅ";
		}
		////////////////////////////
		else if (romaji[0] == L'g')
		{
			if (romaji == L"ga")
				return L"が";
			else if (romaji == L"gi")
				return L"ぎ";
			else if (romaji == L"gu")
				return L"ぐ";
			else if (romaji == L"ge")
				return L"げ";
			else if (romaji == L"go")
				return L"ご";
			else if (romaji == L"gya")
				return L"ぎゃ";
			else if (romaji == L"gyo")
				return L"ぎょ";
			else if (romaji == L"gyu")
				return L"ぎゅ";
		}
		////////////////////////////
		else if (romaji[0] == L's' || romaji[0] == L'c')
		{
			if (romaji == L"sa")
				return L"さ";
			else if (romaji == L"si" || romaji == L"shi" || romaji == L"ci")
				return L"し";
			else if (romaji == L"su")
				return L"す";
			else if (romaji == L"se" || romaji == L"ce")
				return L"せ";
			else if (romaji == L"so")
				return L"そ";
			else if (romaji == L"sya" || romaji == L"sha" || romaji == L"cya")
				return L"しゃ";
			else if (romaji == L"syu"|| romaji == L"shu" || romaji == L"cyo")
				return L"しゅ";
			else if (romaji == L"syo"|| romaji == L"sho" || romaji == L"cyu")
				return L"しょ";
		}
		////////////////////////////
		else if (romaji[0] == L'z' || romaji[0] == L'j')
		{
			if (romaji == L"za")
				return L"ざ";
			else if (romaji == L"zi" || romaji == L"ji")
				return L"じ";
			else if (romaji == L"zu")
				return L"ず";
			else if (romaji == L"ze")
				return L"ぜ";
			else if (romaji == L"zo")
				return L"ぞ";
			else if (romaji == L"zya" || romaji == L"ja" || romaji == L"jya")
				return L"じゃ";
			else if (romaji == L"zyu" || romaji == L"ju"  || romaji == L"jyu")
				return L"じゅ";
			else if (romaji == L"zyo" || romaji == L"jo" || romaji == L"jyo")
				return L"じょ";
		}
		////////////////////////////
		else if (romaji[0] == L't' || romaji[0] == L'c')
		{
			if (romaji == L"ta")
				return L"た";
			else if (romaji == L"ti" || romaji == L"chi")
				return L"ち";
			else if (romaji == L"tu" || romaji == L"tsu")
				return L"つ";
			else if (romaji == L"te")
				return L"て";
			else if (romaji == L"to")
				return L"と";
			else if (romaji == L"tya" || romaji == L"cha")
				return L"ちゃ";
			else if (romaji == L"tyu" || romaji == L"chu")
				return L"ちゅ";
			else if (romaji == L"tyo" || romaji == L"cho")
				return L"ちょ";
		}
		////////////////////////////
		else if (romaji[0] == L'd')
		{
			if (romaji == L"da")
				return L"だ";
			else if (romaji == L"di")
				return L"ぢ";
			else if (romaji == L"du")
				return L"づ";
			else if (romaji == L"de")
				return L"で";
			else if (romaji == L"do")
				return L"ど";
			else if (romaji == L"dya")
				return L"ぢゃ";
			else if (romaji == L"dyu")
				return L"ぢゅ";
			else if (romaji == L"dyo")
				return L"ぢょ";
		}
		////////////////////////////
		else if (romaji[0] == L'n')
		{
			if (romaji == L"na")
				return L"な";
			else if (romaji == L"ni")
				return L"に";
			else if (romaji == L"nu")
				return L"ぬ";
			else if (romaji == L"ne")
				return L"ね";
			else if (romaji == L"no")
				return L"の";
			else if (romaji == L"nya")
				return L"にゃ";
			else if (romaji == L"nyu")
				return L"にゅ";
			else if (romaji == L"nyo")
				return L"にょ";
			else if (romaji == L"n")
				return L"ん";
		}
		////////////////////////////
		else if (romaji[0] == L'h' || romaji[0] == L'f')
		{
			if (romaji == L"ha")
				return L"は";
			else if (romaji == L"hi")
				return L"ひ";
			else if (romaji == L"fu" || romaji == L"hu")
				return L"ふ";
			else if (romaji == L"he")
				return L"へ";
			else if (romaji == L"ho")
				return L"ほ";
			else if (romaji == L"hya")
				return L"ひゃ";
			else if (romaji == L"hyu")
				return L"ひゅ";
			else if (romaji == L"hyo")
				return L"ひょ";
			else if (romaji == L"fa")
				return L"ふぁ";
			else if (romaji == L"fe")
				return L"ふぇ";
			else if (romaji == L"fi")
				return L"ふぃ";
			else if (romaji == L"fo")
				return L"ふぉ";
		}
		////////////////////////////
		else if (romaji[0] == L'b')
		{
			if (romaji == L"ba")
				return L"ば";
			else if (romaji == L"bi")
				return L"び";
			else if (romaji == L"bu")
				return L"ぶ";
			else if (romaji == L"be")
				return L"べ";
			else if (romaji == L"bo")
				return L"ぼ";
			else if (romaji == L"bya")
				return L"びゃ";
			else if (romaji == L"byu")
				return L"びゅ";
			else if (romaji == L"byo")
				return L"びょ";
		}
		////////////////////////////
		else if (romaji[0] == L'p')
		{
			if (romaji == L"pa")
				return L"ぱ";
			else if (romaji == L"pi")
				return L"ぴ";
			else if (romaji == L"pu")
				return L"ぷ";
			else if (romaji == L"pe")
				return L"ぺ";
			else if (romaji == L"po")
				return L"ぽ";
			else if (romaji == L"pya")
				return L"ぴゃ";
			else if (romaji == L"pyu")
				return L"ぴゅ";
			else if (romaji == L"pyo")
				return L"ぴょ";
		}
		////////////////////////////
		else if (romaji[0] == L'm')
		{
			if (romaji == L"ma")
				return L"ま";
			else if (romaji == L"mi")
				return L"み";
			else if (romaji == L"mu")
				return L"む";
			else if (romaji == L"me")
				return L"め";
			else if (romaji == L"mo")
				return L"も";
			else if (romaji == L"mya")
				return L"みゃ";
			else if (romaji == L"myu")
				return L"みゅ";
			else if (romaji == L"myo")
				return L"みょ";
		}
		////////////////////////////
		else if (romaji[0] == L'y')
		{
			if (romaji == L"ya")
				return L"や";
			else if (romaji == L"yu")
				return L"ゆ";
			else if (romaji == L"yo")
				return L"よ";
		}
		////////////////////////////
		else if (romaji[0] == L'r')
		{
			if (romaji == L"ra")
				return L"ら";
			else if (romaji == L"ri")
				return L"り";
			else if (romaji == L"ru")
				return L"る";
			else if (romaji == L"re")
				return L"れ";
			else if (romaji == L"ro")
				return L"ろ";
			else if (romaji == L"rya")
				return L"りゃ";
			else if (romaji == L"ryu")
				return L"りゅ";
			else if (romaji == L"ryo")
				return L"りょ";
		}
		////////////////////////////
		else if (romaji[0] == L'w')
		{
			if (romaji == L"wa")
				return L"わ";
			else if (romaji == L"wo")
				return L"を";
			else if (romaji == L"we")
				return L"うぇ";
		}
		////////////////////////////
		break;
	////////////////////////////////////////////////////////////
	case WT_KATAKANA:
		if (romaji == L"a")
			return L"ア";
		else if (romaji == L"e")
			return L"エ";
		else if (romaji == L"i")
			return L"イ";
		else if (romaji == L"o")
			return L"オ";
		else if (romaji == L"u")
			return L"ウ";
		////////////////////////////
		else if (romaji.size() >= 2 && (romaji[0] == L'k' || romaji[0] == L'c') && romaji[1] != L'h')
		{
			if (romaji == L"ka" || romaji == L"ca")
				return L"カ";
			else if (romaji == L"ki")
				return L"キ";
			else if (romaji == L"ku" || romaji == L"сu")
				return L"ク";
			else if (romaji == L"ke")
				return L"ケ";
			else if (romaji == L"ko" || romaji == L"co")
				return L"コ";
			else if (romaji == L"kya")
				return L"キャ";
			else if (romaji == L"kyo")
				return L"キョ";
			else if (romaji == L"kyu")
				return L"キュ";
		}
		////////////////////////////
		else if (romaji[0] == L'g')
		{
			if (romaji == L"ga")
				return L"ガ";
			else if (romaji == L"gi")
				return L"ギ";
			else if (romaji == L"gu")
				return L"グ";
			else if (romaji == L"ge")
				return L"ゲ";
			else if (romaji == L"go")
				return L"ゴ";
			else if (romaji == L"gya")
				return L"ギャ";
			else if (romaji == L"gyo")
				return L"ギョ";
			else if (romaji == L"gyu")
				return L"ギュ";
		}
		////////////////////////////
		else if (romaji[0] == L's' || romaji[0] == L'c')
		{
			if (romaji == L"sa")
				return L"サ";
			else if (romaji == L"si" || romaji == L"shi" || romaji == L"ci")
				return L"シ";
			else if (romaji == L"su")
				return L"ス";
			else if (romaji == L"se" || romaji == L"ce")
				return L"セ";
			else if (romaji == L"so")
				return L"ソ";
			else if (romaji == L"sya" || romaji == L"sha" || romaji == L"cya")
				return L"シャ";
			else if (romaji == L"syu"|| romaji == L"shu" || romaji == L"cyo")
				return L"シュ";
			else if (romaji == L"syo"|| romaji == L"sho" || romaji == L"cyu")
				return L"ショ";
		}
		////////////////////////////
		else if (romaji[0] == L'z' || romaji[0] == L'j')
		{
			if (romaji == L"za")
				return L"ザ";
			else if (romaji == L"zi" || romaji == L"ji")
				return L"ジ";
			else if (romaji == L"zu")
				return L"ズ";
			else if (romaji == L"ze")
				return L"ゼ";
			else if (romaji == L"zo")
				return L"ゾ";
			else if (romaji == L"zya" || romaji == L"ja" || romaji == L"jya")
				return L"ジャ";
			else if (romaji == L"zyu" || romaji == L"ju"  || romaji == L"jyu")
				return L"ジュ";
			else if (romaji == L"zyo" || romaji == L"jo" || romaji == L"jyo")
				return L"ジョ";
		}
		////////////////////////////
		else if (romaji[0] == L't' || romaji[0] == L'c')
		{
			if (romaji == L"ta")
				return L"タ";
			else if (romaji == L"ti" || romaji == L"chi")
				return L"チ";
			else if (romaji == L"tu" || romaji == L"tsu")
				return L"ツ";
			else if (romaji == L"te")
				return L"テ";
			else if (romaji == L"to")
				return L"ト";
			else if (romaji == L"tya" || romaji == L"cha")
				return L"チャ";
			else if (romaji == L"tyu" || romaji == L"chu")
				return L"チュ";
			else if (romaji == L"tyo" || romaji == L"cho")
				return L"チョ";
		}
		////////////////////////////
		else if (romaji[0] == L'd')
		{
			if (romaji == L"da")
				return L"ダ";
			else if (romaji == L"di")
				return L"ヂ";
			else if (romaji == L"du")
				return L"ヅ";
			else if (romaji == L"de")
				return L"デ";
			else if (romaji == L"do")
				return L"ド";
			else if (romaji == L"dya")
				return L"ヂャ";
			else if (romaji == L"dyu")
				return L"ヂュ";
			else if (romaji == L"dyo")
				return L"ヂョ";
		}
		////////////////////////////
		else if (romaji[0] == L'n')
		{
			if (romaji == L"na")
				return L"ナ";
			else if (romaji == L"ni")
				return L"ニ";
			else if (romaji == L"nu")
				return L"ヌ";
			else if (romaji == L"ne")
				return L"ネ";
			else if (romaji == L"no")
				return L"ノ";
			else if (romaji == L"nya")
				return L"ニャ";
			else if (romaji == L"nyu")
				return L"ニュ";
			else if (romaji == L"nyo")
				return L"ニョ";
			else if (romaji == L"n")
				return L"ン";
		}
		////////////////////////////
		else if (romaji[0] == L'h' || romaji[0] == L'f')
		{
			if (romaji == L"ha")
				return L"ハ";
			else if (romaji == L"hi")
				return L"ヒ";
			else if (romaji == L"fu" || romaji == L"hu")
				return L"フ";
			else if (romaji == L"he")
				return L"ヘ";
			else if (romaji == L"ho")
				return L"ホ";
			else if (romaji == L"hya")
				return L"ヒャ";
			else if (romaji == L"hyu")
				return L"ヒュ";
			else if (romaji == L"hyo")
				return L"ヒョ";
			else if (romaji == L"fa")
				return L"ファ";
			else if (romaji == L"fe")
				return L"フェ";
			else if (romaji == L"fi")
				return L"フィ";
			else if (romaji == L"fo")
				return L"フォ";
		}
		////////////////////////////
		else if (romaji[0] == L'b')
		{
			if (romaji == L"ba")
				return L"バ";
			else if (romaji == L"bi")
				return L"ビ";
			else if (romaji == L"bu")
				return L"ブ";
			else if (romaji == L"be")
				return L"ベ";
			else if (romaji == L"bo")
				return L"ボ";
			else if (romaji == L"bya")
				return L"ビャ";
			else if (romaji == L"byu")
				return L"ビュ";
			else if (romaji == L"byo")
				return L"ビョ";
		}
		////////////////////////////
		else if (romaji[0] == L'p')
		{
			if (romaji == L"pa")
				return L"パ";
			else if (romaji == L"pi")
				return L"ピ";
			else if (romaji == L"pu")
				return L"プ";
			else if (romaji == L"pe")
				return L"ペ";
			else if (romaji == L"po")
				return L"ポ";
			else if (romaji == L"pya")
				return L"ピャ";
			else if (romaji == L"pyu")
				return L"ピュ";
			else if (romaji == L"pyo")
				return L"ピョ";
		}
		////////////////////////////
		else if (romaji[0] == L'm')
		{
			if (romaji == L"ma")
				return L"マ";
			else if (romaji == L"mi")
				return L"ミ";
			else if (romaji == L"mu")
				return L"ム";
			else if (romaji == L"me")
				return L"メ";
			else if (romaji == L"mo")
				return L"モ";
			else if (romaji == L"mya")
				return L"ミャ";
			else if (romaji == L"myu")
				return L"ミュ";
			else if (romaji == L"myo")
				return L"ミョ";
		}
		////////////////////////////
		else if (romaji[0] == L'y')
		{
			if (romaji == L"ya")
				return L"ヤ";
			else if (romaji == L"yu")
				return L"ユ";
			else if (romaji == L"yo")
				return L"ヨ";
		}
		////////////////////////////
		else if (romaji[0] == L'r')
		{
			if (romaji == L"ra")
				return L"ラ";
			else if (romaji == L"ri")
				return L"リ";
			else if (romaji == L"ru")
				return L"ル";
			else if (romaji == L"re")
				return L"レ";
			else if (romaji == L"ro")
				return L"ロ";
			else if (romaji == L"rya")
				return L"リャ";
			else if (romaji == L"ryu")
				return L"リュ";
			else if (romaji == L"ryo")
				return L"リョ";
		}
		////////////////////////////
		else if (romaji[0] == L'w')
		{
			if (romaji == L"wa")
				return L"ワ";
			else if (romaji == L"wo")
				return L"ヲ";
			else if (romaji == L"we")
				return L"ウェ";
		}
		else if (romaji[0] == L'-')
		{
			return L"ー";
		}
		////////////////////////////
		break;
	default:
		break;
	}
	return s;
}

///////////////////////////////////////////////////////////////////

std::wstring RomajiFilter(std::wstring romaji)
{
	for (size_t i = 0; i < romaji.size(); i++)
	{
		if (i > 0)
		{
            if (romaji[i] == 'o' && romaji[i - 1] == L'o' && i == romaji.size() - 1)
				romaji[i] = L'u';
		}
		if (romaji[i] == L's' && romaji[i + 1] == L'i')
		{
			romaji.insert(i + 1, L"h");
		}
		if (romaji[i] == L'l')
			romaji[i] = L'r';
	}
	return romaji;
}

wstring MakeKana(wstring romaji, WordType type)
{
	vector<wstring> ss;
	wstring stemp;
	romaji = RomajiFilter(romaji);
	if (romaji.empty())
		return romaji;
	for (size_t i = 0; i < romaji.size(); i++)
	{
		wchar_t c = romaji[i];
		wchar_t n = L'\0';
		if (i + 1 < romaji.size())
			n = romaji[i + 1];
		stemp += c;
		if (IsVowel(c))
		{
			if (c == L'y')
				continue;
			ss.push_back(stemp);
			stemp.clear();
			continue;
		}
		else if (c == L'-')
		{
			ss.push_back(stemp);
			stemp.clear();
			continue;
		}
		else
		{
			if (c == L'n' && !IsVowel(n))
			{
				ss.push_back(stemp);
				stemp.clear();
				continue;
			}
			else
				continue;
		}
	}
	stemp.clear();
	wstring kana;
	for (size_t i = 0; i < ss.size(); i++)
	{
		wstring r = ss[i];
		wstring skana = MakeSyllable(r, type);
		if (skana.empty())
			return L""; //error
		kana += skana;
	}
	return kana;
}

///////////////////////////////////////////////////////////////////

#include <fstream>
#include <wchar.h>
#include <wctype.h>

bool LoadWordsLibs()
{
	WordsLibrary.hiragana.clear();
	WordsLibrary.katakana.clear();
	wfstream hg("hiragana.txt", ios::in | ios::out);
	wfstream kk("katakana.txt", ios::in | ios::out);
	if (hg.is_open())
	{
		while (!hg.eof())
		{
			word w;
			hg >> w.romaji;
			if (w.romaji.empty())
				continue;
			w.kana = MakeKana(w.romaji, WT_HIRAGANA);
			if (!w.kana.empty())
				WordsLibrary.hiragana.push_back(w);
		}
		hg.close();
	}
	if (kk.is_open())
	{
		while (!kk.eof())
		{
			word w;
			kk >> w.romaji;
			if (w.romaji.empty())
				continue;
			w.kana = MakeKana(w.romaji, WT_KATAKANA);
			if (!w.kana.empty())
				WordsLibrary.katakana.push_back(w);
		}
		kk.close();
	}
	return true;
}
